/*
 * @Author: sjf 1758142861@qq.com
 * @Date: 2023-03-21 19:21:36
 * @LastEditors: sjf 1758142861@qq.com
 * @LastEditTime: 2023-03-21 19:40:41
 * @FilePath: /D_C_lib/thread_safety/ticket_test.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */



//模拟在不加锁的情况4个线程抢票的情况
// 1. 多个执行流进行安全访问的共享资源 - 临界资源
// 2. 我们把多个执行流中，访问临界资源的代码 -- 临界区 -- 往往是线程代码的很小的一部分
// 3. 想让多个线程串行访问共享资源 -- 互斥
// 4. 对一个资源进行访问的时候，要么不做，要么做完 -- 原子性 ， 不是原子性的情况 -- 一个对资源进行的操作，如果只用一条汇编就能完成 -- 原子性
// 反之：不是原子的 -- 当前理解，方便表述

// 提出解决方案：加锁！


// 就需要尽可能的让多个线程交叉执行
// 多个线程交叉执行本质：就是让调度器尽可能的频繁发生线程调度与切换
// 线程一般在什么时候发生切换呢？时间片到了，来了更高优先级的线程，线程等待的时候。
// 线程是在什么时候检测上面的问题呢？从内核态返回用户态的时候，线程要对调度状态进行检测，如果可以，就直接发生线程切换
#include <iostream>
#include <pthread.h>
#include <unistd.h>

//静态分配
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int ticket = 1000;

void *_start_coutine(void *args)
{
    const char *name = static_cast<const char *>(args);
    while (true)
    {
        pthread_mutex_lock(&lock);
        if (ticket > 0)
        {
            usleep(12345);
            std::cout << "name:" << name << "get one ticket" << ticket-- 
            << std::endl;
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
    }
    std::cout << name << ":quit" << std::endl;
    return nullptr;
    //pthread_exit((void *)0);
}

int main()
{
    pthread_t tid1, tid2, tid3, tid4;
    pthread_create(&tid1, nullptr, _start_coutine, (void *)"new thread 1");
    pthread_create(&tid2, nullptr, _start_coutine, (void *)"new thread 2");
    pthread_create(&tid3, nullptr, _start_coutine, (void *)"new thread 3");
    pthread_create(&tid4, nullptr, _start_coutine, (void *)"new thread 4");

    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);
    pthread_join(tid4, nullptr);
}